
#include "CSubject.h"
#include "IObserver.h"
#include "CDivider.h"
#include "CMultiplicator.h"
#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>


using namespace std;

// helper operation
bool checkIfStringIsNumber(string theString);
void printProgramInfo();
void printSupportedCommands();


int main()
{
    CSubject* itsSubject = new CSubject();

    IObserver* itsDivider = new CDivider(itsSubject, "'Divider Observer'");
    IObserver* itsMultiplicator = new CMultiplicator(itsSubject, "'Multiplicator Observer'");

    printProgramInfo();
    printSupportedCommands();
      
    
    
    while (1)
    {
        string dataInput ("");
        

        cout << endl << "------------------------" << endl;
        cout << "Enter command or number: ";
        cin >> dataInput;
        
        
        // Command 'attachDivider'
        // -----------------------
        
        if (0 == dataInput.compare("attachDivider"))
        {
            if (false == itsSubject->attach(itsDivider))
            {
                cout << "This observer is already attached" << endl;
            }            
        }
        
        // Command 'detachDivider'
        // -----------------------
        
        else if (dataInput == "detachDivider")
        {
            itsSubject->detach(itsDivider);
        }
        
        // Command 'attachMultiplicator'
        // -----------------------------
        
        else if (dataInput == "attachMultiplicator")
        {
            if (false == itsSubject->attach(itsMultiplicator))
            {
                cout << "This observer is already attached" << endl;
            }            
        }
        
        // Command 'detachMultiplicator'
        // -----------------------------
        
        else if (dataInput == "detachMultiplicator")
        {
            itsSubject->detach(itsMultiplicator);
        }
        
        // Command 'setDivisor'
        // --------------------
        
        else if (dataInput == "setDivisor")
        {
            cout << "Enter divisor: ";
            cin >> dataInput;
            
            if (true == checkIfStringIsNumber(dataInput))
            {
                itsDivider->setDivisor(atoi(dataInput.c_str()));
            }
        }

        // Command 'setMultiplier'
        // -----------------------
        
        else if (dataInput == "setMultiplier")
        {
            cout << "Enter multiplier: ";
            cin >> dataInput;
            
            if (true == checkIfStringIsNumber(dataInput))
            {
                itsMultiplicator->setMultiplier(atoi(dataInput.c_str()));
            }
        }            
        
        // Command 'exit'
        // --------------
        
        else if (dataInput == "exit")
        {
            cout << "Au revoir!" << endl;
            return 0;
         }
        
        //  Check if its a number --> set the new subject data
        // ---------------------------------------------------
        
        else if (true == checkIfStringIsNumber(dataInput))
        {
            itsSubject->setData(atoi(dataInput.c_str()));
        }
        
        // Invalid command or number
        // -------------------------
        
        else
        {
            cout << "Invalid command or number!" << endl;
            
            printSupportedCommands();
        }
    }

    return 0;

}


// Helper operation(s)
// -------------------

bool checkIfStringIsNumber(string theString)
{
    for (int i = 0; i < static_cast<int>(theString.size()); i++)
    {
        if (0 == isdigit(theString[i]))
        {
            return false;
        }            
    }
    
    return true;
}


void printProgramInfo()
{
    cout    << endl
            << "----------------------------------------------------------------------" << endl
            << "This program is implemented using the observer design pattern." << endl
            << endl
            << "Two observers can be attached / detached to the subject." << endl
            << "This two observers are implemented as a divider and as a multiplier." << endl
            << "If new data (integer value) is applied to the subject," << endl
            << "the subject itselfs calls the update method of all attached observers." << endl
            << "The observer knows that its necessary to get the new data from" << endl
            << "the subject and do a division or a multiplication." << endl
            << endl
            << "----------------------------------------------------------------------" << endl;      
}


void printSupportedCommands()
{
    cout     << "Supported commands are:" << endl
            << endl
            << "\t- attachDivider" << endl
            << "\t- detachDivider" << endl
            << "\t- attachMultiplicator" << endl
            << "\t- detachMultiplicator" << endl
            << "\t- setMultiplier" << endl
            << "\t- setDivisor" << endl
            << "\t- exit" << endl
            << "\t- or just a number (for example 21)" << endl;
}
